package com.example.springboot.controller.tokenExcludeRepeatFormSubmit;

import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * token机制，每次接口请求前先获取一个token，然后再下次请求的时候在请求的header体中加上这个token，
 * 后台进行验证，如果验证通过删除token，下次请求再次判断token。
 * @Author:ChenZhangKun
 * @Date: 2021/12/22 10:16
 */
@RestController
@RequestMapping("/czk/token")
@Api(tags = "token防止重复提交")
@Slf4j
public class ExcludeFormByToken {
    private static final String PREFIX = "CZK_";

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 拿到token
     *
     * @param userId
     * @return
     */
    @GetMapping("/get/{userId}")
    public String getToken(@PathVariable Integer userId) {
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        //
        String key = PREFIX + uuid;
        // 存储
        redisTemplate.opsForValue().set(key, userId + "", 3, TimeUnit.SECONDS);
        System.out.println(redisTemplate.opsForValue().get(key));
        return uuid;
    }

    /**
     * 校验
     *
     * @param token
     * @param userId
     * @return
     */
    @GetMapping("/vertify/{token}/{userId}")
    public boolean vertify(@PathVariable("token") String token, @PathVariable("userId") Integer userId) {
        // 设置 Lua 脚本，其中 KEYS[1] 是 key，KEYS[2] 是 value
        String script = "if redis.call('get', KEYS[1]) == KEYS[2] then return redis.call('del', KEYS[1]) else return 0 end";
        DefaultRedisScript<Long> defaultRedisScript = new DefaultRedisScript<>(script, Long.class);
        // 执行lua脚本
        Long result = redisTemplate.execute(defaultRedisScript, Arrays.asList(PREFIX + token, userId + ""));
        // 根据返回结果判断是否成功成功匹配并删除 Redis 键值对，若果结果不为空和0，则验证通过
        if (result != null && result != 0L) {
            log.info("验证 token={},key={},value={} 成功", token, PREFIX + token, userId);
            return true;
        }
        log.info("验证 token={},key={},value={} 失败", token, PREFIX + token, userId);
        return false;
    }

}
